using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.ComponentModel;

using System.Collections.Generic;

using DAL.util;

namespace DAL.sql2005.common
{
    public class BaseManager<T> : DataAccessManager
    {
        private const string C_DEFAULTDB_NAME = "DefaultDB";
        /// <summary>
        /// Initializes a new instance of the <see cref="BaseManager&lt;T&gt;"/> class.
        /// </summary>
        public BaseManager()
            : base(C_DEFAULTDB_NAME)
        {

        }


        /// <summary>
        /// Initializes a new instance of the <see cref="BaseManager&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="DBConnstring">The DB connstring.</param>
        public BaseManager(string DBConnstring)
            : base(DBConnstring)
        {

        }

        /// <summary>
        /// Gets the list from SQL text.
        /// </summary>
        /// <param name="sql">The SQL.</param>
        /// <returns></returns>
        protected List<T> GetListFromSqlText(string sql)
        {
            SqlCommand DBCommand = new SqlCommand();
            DBCommand.CommandType = CommandType.Text;
            DBCommand.CommandText = sql;

            if (DBConn.State != ConnectionState.Open)
                DBConn.Open();

            DBCommand.Connection = DBConn;

            SqlDataReader DR = DBCommand.ExecuteReader();

            List<T> ListItems = new List<T>();

            if (DR.HasRows)
                while (DR.Read())
                {
                    object[] listOfValues = (object[])Array.CreateInstance(typeof(object), DR.FieldCount);
                    DR.GetValues(listOfValues);

                    ListItems.Add(
                        GetNewItem(listOfValues)
                        );
                }

            DR.Close();

            DBCommand = null;

            DBConn.Close();
            DBConn = null;

            return ListItems;

        }

        /// <summary>
        /// Gets the list.
        /// </summary>
        /// <param name="sproc">The sproc.</param>
        /// <param name="list">The list.</param>
        /// <returns></returns>
        protected List<T> GetListFromStoredProcedure(string sproc, params object[] list)
        {
            SqlCommand DBCommand = new SqlCommand();
            DBCommand.CommandType = CommandType.StoredProcedure;
            DBCommand.CommandText = sproc;

            if (DBConn.State != ConnectionState.Open)
                DBConn.Open();

            DBCommand.Connection = DBConn;

            SqlCommandBuilder.DeriveParameters(DBCommand);

            if (list == null && DBCommand.Parameters.Count > 0)
                throw new Exception(" Wrong number of parameters sent to method : ExecuteNonQuery");

            int Count;
            // the first 'parameter' in a parameter collection
            // is the RETURN_VALUE = which we ignore :
            for (Count = 1; Count < DBCommand.Parameters.Count; Count++)
            {
                DBCommand.Parameters[Count].Value = list[Count - 1];
            }

            SqlDataReader DR = DBCommand.ExecuteReader();

            List<T> ListItems = new List<T>();

            if (DR.HasRows)
                while (DR.Read())
                {
                    object[] listOfValues = (object[])Array.CreateInstance(typeof(object), DR.FieldCount);
                    DR.GetValues(listOfValues);



                    ListItems.Add(
                        GetNewItem(listOfValues)
                        );
                }

            DR.Close();

            DBCommand = null;

            DBConn.Close();
            DBConn = null;

            return ListItems;
        }


        /// <summary>
        /// Gets the item.
        /// </summary>
        /// <param name="sproc">The sproc.</param>
        /// <param name="list">The list.</param>
        /// <returns></returns>
        protected T GetItemFromStoredProcedure(string sproc, params object[] list)
        {
            SqlCommand DBCommand = new SqlCommand();
            DBCommand.CommandType = CommandType.StoredProcedure;
            DBCommand.CommandText = sproc;

            if (DBConn.State != ConnectionState.Open)
                DBConn.Open();

            DBCommand.Connection = DBConn;

            SqlCommandBuilder.DeriveParameters(DBCommand);

            if (list == null && DBCommand.Parameters.Count > 0)
                throw new Exception(" Wrong number of parameters sent to method : ExecuteNonQuery");

            int Count;
            // the first 'parameter' in a parameter collection
            // is the RETURN_VALUE = which we ignore :
            for (Count = 1; Count < DBCommand.Parameters.Count; Count++)
            {
                DBCommand.Parameters[Count].Value = list[Count - 1];
            }

            SqlDataReader DR = DBCommand.ExecuteReader();

            T NewItem = default(T);

            if (DR.HasRows)
            {
                DR.Read();
                object[] listOfValues = (object[])Array.CreateInstance(typeof(object), DR.FieldCount);
                DR.GetValues(listOfValues);



                NewItem = GetNewItem(listOfValues);
            }

            DR.Close();

            DBCommand = null;

            DBConn.Close();
            DBConn = null;

            return NewItem;
        }

        /// <summary>
        /// Gets the new item.
        /// </summary>
        /// <param name="list">The list.</param>
        /// <returns></returns>
        public virtual T GetNewItem(params object[] list)
        {
            throw new Exception("GetFromDataReaderRow should always be overriden");
        }

        /// <summary>
        /// Sorts the specified list.
        /// </summary>
        /// <param name="listToSort">The list to sort.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="ascending">if set to <c>true</c> [ascending].</param>
        /// <returns></returns>
        public List<T> Sort(List<T> listToSort, string propertyName, bool ascending)
        {

            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
            PropertyDescriptor propertyDesc = properties.Find(propertyName, true);

            // Apply and set the sort, if items to sort
            PropertyComparer<T> pc = new PropertyComparer<T>(propertyDesc, (ascending) ? ListSortDirection.Ascending : ListSortDirection.Descending);
            listToSort.Sort(pc);

            return listToSort;
        }


        /// <summary>
        /// Gets a page of data from a list.
        /// </summary>
        /// <param name="parentList">The parent list.</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <param name="pageNo">The page no.</param>
        /// <returns></returns>
        public List<T> GetPage(List<T> parentList, int pageSize, int pageNo)
        {
            if ((pageNo * pageSize) + pageSize < parentList.Count)
            {
                return parentList.GetRange(pageSize * pageNo, pageSize);
            }
            else
            {
                int itemCount = parentList.Count - (pageSize * pageNo);

                return parentList.GetRange(pageSize * pageNo, itemCount);
            }
        }

        /// <summary>
        /// Gets the page count of a list.
        /// </summary>
        /// <param name="parentList">The parent list.</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <returns></returns>
        public int GetPageCount(List<T> parentList, int pageSize)
        {
            if (pageSize <= 0)
            {
                return 1;
            }
            else
            {
                return parentList.Count % pageSize == 0 ?
                    parentList.Count / pageSize :
                    (parentList.Count - (parentList.Count % pageSize) + pageSize) / pageSize;
            }
        }


        //public  object[] ConvertDBNulls(params object[] list)        
        //{
        //    for (int i = 0; i < list.Length; i++)
        //    {
        //        if (list[i] == DBNull.Value)
        //            list[i] = null;
        //    }
        //    return list;
        //}

    }
}
